package main

import "fmt"

/*
通道缓冲区
通道可以设置缓冲区，通过make 的第二个参数指定缓冲区大小：
ch := make(chan int ,100)
带缓冲区的通道允许发送端的数据发送和接收端的数据获取处于异步状态，
就是说发送端发送的数据可以放在缓冲区里面，可以等待接收端区获取数据，
而不是立刻需要接收端去获取数据

不过由于缓存区的大小是有限的，所以还是逆序有接收端来接收数据的，
否则缓冲区一满，数据发送端就无法再发送数据了

注意：如果通道不带缓冲，发送方会阻塞直到接收方从通道中接受了值，
如果通道带缓存，发送方则会阻塞直到发送的值被拷贝到缓冲区内；如果缓冲区已满，
则意味着需要等待直到某个接收方获取到一个值，接收方在有值可以接受之前一直会阻塞

*/

//func main() {
//	// 这里我们定义了一个可以存储整数类型的带缓冲通道
//	// 缓冲区大小为2
//	ch := make(chan int, 2)
//
//	// 因为 ch 是带缓冲的通道，我们可以同时发送两个数据
//	// 而不用立刻需要去同步读取数据
//	ch <- 1
//	ch <- 2
//
//	// 获取这两个数据
//	fmt.Println(<-ch)
//	fmt.Println(<-ch)
//}

/*
go 遍历通道与关闭通道
Go 通过 range 关键字来实现遍历读取到的数据，类似于与数组或切片。
v, ok := <-ch
如果通道接收不到数据后 ok 就为 false，这时通道就可以使用 close() 函数来关闭。
*/

func fibonacci(n int, c chan int) {
	x, y := 0, 1
	for i := 0; i < n; i++ {
		c <- x
		x, y = y, x+y
	}
	close(c)
}

func main() {
	c := make(chan int, 10)
	//go内置函数 cap(v Type) int 返回指定类型的容量，根据不同类型，返回意义不同。
	go fibonacci(cap(c), c)
	// range 函数遍历每个从通道接收到的数据，
	//因为 c 在发送完 10 个数据之后就关闭了通道，所以这里我们 range 函数在接收到 10 个数据之后就结束了。
	//如果上面的 c 通道不关闭，那么 range 函数就不会结束，从而在接收第 11 个数据的时候就阻塞了。
	for i := range c {
		fmt.Println(i)
	}
}
